#include <stdlib.h>
#include <string.h>
#include "symbol.h"

#define TableSize 4096

struct symbol {
	char* name; // the string pointed by 'name' must be allocated in the heap
	symbol* next; // to form the linked list
};

static symbol* hashTable[TableSize] = {NULL};

static int hash(char* str) {
	// assert(str)
	char* p = str;
	int hashIndex = 0;
	while(*p) {
		hashIndex = (hashIndex * 65599 + *p) % TableSize;
		++p;
	}
	return hashIndex;
}

symbol* S_symbol(char* str) {
	// assert(str)
	int hashIndex = hash(str);
	for(symbol* p = hashTable[hashIndex]; p; p = p->next) {
		if(!strcmp(p->name, str))
			return p;
	}
	symbol* sym = (symbol*)malloc(sizeof(*sym));
	sym->name = str;
	sym->next = hashTable[hashIndex];
	hashTable[hashIndex] = sym;
	return sym;
}

char* S_name(symbol* sym) {
	// assert(sym)
	return sym->name;
}

static void S_free(symbol* sym) {
	// free the memory about 'sym'
	if(!sym)
		return;
	free(sym->name);
	S_free(sym->next);
	free(sym);	
}

void S_clear() {
	for(int i = 0; i < TableSize; ++i)
		S_free(hashTable[i]);
}
